using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace SimpleGame.Utils
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class InputHandler : Microsoft.Xna.Framework.GameComponent
    {
        #region Fields

        // The keyboard states are used to check if a key is released, pressed or down
        private static KeyboardState currentKeyboardState;
        private static KeyboardState oldKeyboardState;

        // The mouse states are used to check if a mouse button is released, pressed or down
        // and to get the current mouse position on the screen
        private static MouseState currentMouseState;
        private static MouseState oldMouseState;

        #endregion

        #region Constructor

        public InputHandler(Game game)
            : base(game)
        {
            // get the current states to begin with state tracking
            currentKeyboardState = Keyboard.GetState();
            currentMouseState = Mouse.GetState();
        }

        #endregion

        #region XNA Methods


        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // set old states and get new state to make sure we can check for pressed buttons
            oldKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();
            oldMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            base.Update(gameTime);
        }

        #endregion

        #region Keyboard Methods

        /// <summary>
        /// Checks if the specific key was just released.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns>True if Key was just released</returns>
        public static bool IsKeyReleased(Keys key)
        {
            return currentKeyboardState.IsKeyUp(key) &&
                oldKeyboardState.IsKeyDown(key);
        }

        /// <summary>
        /// Checks if the specific key was just pressed.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns>True if Key was just pressed</returns>
        public static bool IsKeyPressed(Keys key)
        {
            return currentKeyboardState.IsKeyDown(key) &&
                oldKeyboardState.IsKeyUp(key);
        }

        /// <summary>
        /// Checks if the specific key is currently down.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns>True if Key is down</returns>
        public static bool IsKeyDown(Keys key)
        {
            return currentKeyboardState.IsKeyDown(key);
        }

        #endregion

        #region Mouse Methods

        /// <summary>
        /// Gets the X mouse coordinate
        /// </summary>
        /// <returns>The X mouse coordinate as int</returns>
        public static int GetMousePositionX()
        {
            return currentMouseState.X;
        }

        /// <summary>
        /// Gets the Y mouse coordinate
        /// </summary>
        /// <returns>The Y mouse coordinate as int</returns>
        public static int GetMousePositionY()
        {
            return currentMouseState.Y;
        }

        /// <summary>
        /// Checks if the left mouse button was just pressed.
        /// </summary>
        /// <returns>True if left mouse button was just pressed</returns>
        public static bool IsLeftMouseButtonPressed()
        {
            return currentMouseState.LeftButton == ButtonState.Pressed &&
                    oldMouseState.LeftButton == ButtonState.Released;
        }

        /// <summary>
        /// Checks if the right mouse button was just pressed.
        /// </summary>
        /// <returns>True if right mouse button was just pressed</returns>
        public static bool IsRightMouseButtonPressed()
        {
            return currentMouseState.RightButton == ButtonState.Pressed &&
                    oldMouseState.RightButton == ButtonState.Released;
        }

        /// <summary>
        /// Checks if the middle mouse button was just pressed.
        /// </summary>
        /// <returns>True if middle mouse button was just pressed</returns>
        public static bool IsMiddleMouseButtonPressed()
        {
            return currentMouseState.MiddleButton == ButtonState.Pressed &&
                    oldMouseState.MiddleButton == ButtonState.Released;
        }

        /// <summary>
        /// Checks if the left mouse button was just released.
        /// </summary>
        /// <returns>True if the left mouse button was just released</returns>
        public static bool IsLeftMouseButtonReleased()
        {
            return currentMouseState.LeftButton == ButtonState.Released &&
                    oldMouseState.LeftButton == ButtonState.Pressed;
        }

        /// <summary>
        /// Checks if the right mouse button was just released.
        /// </summary>
        /// <returns>True if the right mouse button was just released</returns>
        public static bool IsRightMouseButtonReleased()
        {
            return currentMouseState.RightButton == ButtonState.Released &&
                    oldMouseState.RightButton == ButtonState.Pressed;
        }

        /// <summary>
        /// Checks if the middle mouse button was just released.
        /// </summary>
        /// <returns>True if the middle mouse button was just released</returns>
        public static bool IsMiddleMouseButtonReleased()
        {
            return currentMouseState.MiddleButton == ButtonState.Released &&
                    oldMouseState.MiddleButton == ButtonState.Pressed;
        }

        /// <summary>
        /// Checks if the left mouse button is currently down.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns>True if the left mouse button is down</returns>
        public static bool IsLeftMouseButtonDown()
        {
            return currentMouseState.LeftButton == ButtonState.Pressed;
        }

        /// <summary>
        /// Checks if the right mouse button is currently down.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns>True if the right mouse button is down</returns>
        public static bool IsRightMouseButtonDown()
        {
            return currentMouseState.RightButton == ButtonState.Pressed;
        }

        /// <summary>
        /// Checks if the middle mouse button is currently down.
        /// </summary>
        /// <param name="key">Key to check</param>
        /// <returns>True if the middle mouse button is down</returns>
        public static bool IsMiddleMouseButtonDown()
        {
            return currentMouseState.MiddleButton == ButtonState.Pressed;
        }

        #endregion
    }
}
